#include "tree.cpp"		//包含二叉树的基本运算 
typedef char ElemType;
 
/*---------
求二叉树中从根结点到叶子结点的路径 
-----------*/
 
//采用先序遍历方法输出所有从叶子结点到根结点的逆路径 
void AllPath1(BTNode *b,ElemType path[],int pathlen){	//path[]存储路径【相当于一个栈】，pathlen记录路径长度 
	int i;							//调用AllPath1函数时，传进来的path[]是空数组，pathlen为0； 
	if(b!=NULL){
		if(b->lchild==NULL && b->rchild==NULL){		//若b为叶子结点
			printf("%c到根结点的逆路径：%c->",b->data,b->data);	//打印叶子结点
			for(i=pathlen-1;i>0;i--)		//打印路径时，并没有修改栈顶指针pathlen的值 
				printf("%c->",path[i]);			//所以每次递归遍历的路径存储在上次递归路径的后面 
			printf("%c\n",path[0]);
		}else{
			path[pathlen] = b->data;	//将当前结点放入路径中 
			pathlen++;					//路径长度加1
			AllPath1(b->lchild,path,pathlen);	//递归扫描左子树
			AllPath1(b->rchild,path,pathlen);	//递归扫描右子树  
		} 
	}
} 
 
 
//采用先序遍历方法输出第一条最长的逆路径
void LongPath1(BTNode *b,ElemType path[],int pathlen,ElemType longpath[],int &longpathlen ){
	int i;												//longpath[]保存当前最长路径，每次递归的路径长度都可能被修改
	if(b==NULL){	//若当前节点为空 
		if(pathlen>longpathlen){	//若当前路径更长，将路径保存 
			for(i=pathlen-1;i>=0;i--)
				longpath[i]=path[i];
			longpathlen= pathlen;
		}
	} else{
		path[pathlen] = b->data;
		pathlen++;
		LongPath1(b->lchild,path,pathlen,longpath,longpathlen);
		LongPath1(b->rchild,path,pathlen,longpath,longpathlen);
	}
} 
 
//采用后序非递归遍历方法输出所有从叶子结点到根结点的逆路径
void AllPath2(BTNode *b){
	BTNode * st[MaxSize];	//定义一个顺序栈st
	int top=-1;			//栈顶指针初始化
	BTNode *p,*r;
	bool flag;
	p=b;
	do{	//至少循环一次 
		while(p!=NULL){		//扫描结点p的所有左下结点并进栈
			top++;
			st[top] = p;	//结点p进栈
			p=p->lchild;	//移动到左孩子 
			
		}
		r=NULL;		//r指向刚刚访问的结点，初始时为空
		flag=true;	//flag为真表示正在处理栈顶结点
		while(top>-1 && flag){	//栈不空且flag为真时进入循环 
			p=st[top];		//取出当前的栈顶结点p
			if(p->rchild == r){		//若结点p的右孩子为空或者为刚刚访问过的结点
				if(p->lchild==NULL && p->rchild==NULL){		//若为叶子结点,输出栈中所有结点值
					printf("%c到根结点逆路径：",p->data);
					for(int i=top;i>0;i--){
						printf("%c->",st[i]->data);
					} 
					printf("%c\n",st[0]->data);
					 
				} 
				top--;		//退栈
				r=p;		//r指向刚访问过的结点 
			}else{
				p=p->rchild;	//转向处理其右子树
				flag=false;		//表示当前不是处理栈顶结点 
			}	 
		} 
	} while(top>-1);	//栈空时，退出循环 
} 
 
//采用层次遍历输出所有从叶子结点到根结点的逆路径 
void AllPath3(BTNode *b){
	//定义顺序队列
	struct snode{
		BTNode *node;		//存放当前结点指针
		int parent;			//存放双亲结点在队列中的位置 
	}Qu[MaxSize]; 
	int front,rear,p;		//定义队头和队尾指针
	front=rear=-1;			//置队列为空队列
	rear++;
	Qu[rear].node=b;		//根结点指针进入队列
	Qu[rear].parent=-1;		//根结点没有双亲结点
	while(front<rear){		//队列不为空
		front++;
		b=Qu[front].node;		//队头出队列
		if(b->lchild==NULL && b->rchild==NULL){	//若b为叶子结点
			printf("%c到根结点逆路径：",b->data);
			p=front;
			while(Qu[p].parent != -1){
				printf("%c->",Qu[p].node->data);
				p=Qu[p].parent;
			} 
			printf("%c\n",Qu[p].node->data);
		} 
		if(b->lchild!=NULL){	//若有左孩子，将其进队
			rear++;
			Qu[rear].node=b->lchild;
			Qu[rear].parent=front; 
			
		}
		if(b->rchild!=NULL){	//若有右孩子，将其进队
			rear++;
			Qu[rear].node=b->rchild;
			Qu[rear].parent=front; 
		}
	} 
	
}
 
int main(){
	BTNode *b;
	ElemType path[MaxSize],longpath[MaxSize];
	int i,longpathlen=0;
	CreatBTree(b,"A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))");
	printf("二叉树b:");
	DispBTree(b);printf("\n");
	printf("先序遍历方法：\n");
	AllPath1(b,path,0);
	LongPath1(b,path,0,longpath,longpathlen);
	printf("第一最长逆路径长度：%d\n",longpathlen);
	printf("第一最长逆路径：");
	for(i=longpathlen-1;i>=0;i--)
		printf("%c",longpath[i]);
	printf("\n");
	printf("后序非递归遍历方法：\n");
	AllPath2(b);
	printf("层次遍历方法：\n");
	AllPath3(b);
	DestroyBTree(b);
	return 1;
}
 
 